package com.choosefine.paycenter.webgateway.settlement.web.controller;

import com.choosefine.paycenter.account.dto.AccountWdDto;
import com.choosefine.paycenter.account.model.*;
import com.choosefine.paycenter.account.service.*;
import com.choosefine.paycenter.channel.ccb.api.handler.CCBWithdrawHandler;
import com.choosefine.paycenter.channel.ccb.api.impl.CCBWithdrawServiceImpl;
import com.choosefine.paycenter.common.dto.JSONResult;
import com.choosefine.paycenter.common.enums.*;
import com.choosefine.paycenter.common.utils.JSONResultGenerator;
import com.choosefine.paycenter.pay.service.ChannelService;
import com.choosefine.paycenter.settlement.dispatcher.WithdrawDispatcher;
import com.choosefine.paycenter.settlement.dto.WithdrawDTO;
import com.choosefine.paycenter.settlement.handler.WithdrawHandler;
import com.choosefine.paycenter.settlement.model.Withdraw;
import com.choosefine.paycenter.settlement.model.WithdrawLog;
import com.choosefine.paycenter.settlement.service.WithDrawBankRoutingService;
import com.choosefine.paycenter.settlement.service.WithdrawBankService;
import com.choosefine.paycenter.settlement.service.WithdrawLogService;
import com.choosefine.paycenter.settlement.service.WithdrawService;
import com.choosefine.paycenter.settlement.vo.WithDrawVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.constraints.NotBlank;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;

/**
 * Comments：
 * Author：Jay Chang
 * Create Date：2017/3/27
 * Modified By：
 * Modified Date：
 * Why & What is modified：
 * Version：v1.0
 */
@Slf4j
@Api(value = "提现", description = "潘钱钦")
@RestController
@RequestMapping("account/withdraw")
public class WithdrawController {
    //    @Autowired
//    CCBWithdrawHandler ccbWithdrawHandler;
    private final static double bigAmount = 50000.00;
    @Autowired
    WithdrawService withdrawService;

    @Autowired
    WithdrawDispatcher withdrawDispatcher;

    @Autowired
    WithdrawBankService withdrawBankService;

    @Autowired
    AccountService accountService;

    @Autowired
    WithdrawLogService withdrawLogService;

    @Autowired
    AccountBankcardService accountBankcardService;

    @Autowired
    ChannelService channelService;

    @Autowired
    WithDrawBankRoutingService withDrawBankRoutingService;

    @Autowired
    AccountBillService accountBillService;

    Withdraw withdraw = null;

    AccountWdDto accountDTO = null;

    WithdrawLog withdrawLog = null;

    @ApiOperation("提现操作")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userCode", dataType = "String", paramType = "header", required = true, value = "租户编码"),
            @ApiImplicitParam(name = "operName", dataType = "String", paramType = "body", required = true, value = "操作员"),
            @ApiImplicitParam(name = "bankCardId", dataType = "Long", paramType = "body", required = true, value = "账户银行id"),
            @ApiImplicitParam(name = "accountId", dataType = "Long", paramType = "body", required = true, value = "账户id"),
            @ApiImplicitParam(name = "amount", dataType = "BigDecimal", paramType = "body", required = true, value = "金额"),
            @ApiImplicitParam(name = "password", dataType = "String", paramType = "body", required = true, value = "支付密码"),
    })
    @PostMapping
    public JSONResult doWithdraw(@RequestHeader("userCode") @NotBlank String userCode,
                                 @Validated @RequestBody WithdrawDTO withdrawDto) {
        AccountBankcard accountBankcard = accountBankcardService.findAccountBankById(withdrawDto.getBankCardId());
        String bankCode = accountBankcard.getBankCode();//添加银行卡的时候，必须提供bankCode（现已经校验）
        String channel = withDrawBankRoutingService.chooseChannel(bankCode);
        WithdrawHandler withdrawHandler = withdrawDispatcher.getWithdrawHandler(channel);
        WithDrawVo withDrawVo = withdrawHandler.buildWithDraw(withdrawDto, userCode);
        withdraw = new Withdraw();
        accountDTO = new AccountWdDto();
        Withdraw withdraw1=withdrawService.selectByWSn(withDrawVo.getWithDrawSn());
        long withdrawId =withdraw1.getId() ;
        //记录提现日志表
        withdrawLog = new WithdrawLog();
        withdrawLog.setAccountName(withDrawVo.getWithDrawRealName());
        withdrawLog.setAmount(new BigDecimal(withDrawVo.getAmount()));
        withdrawLog.setRequestSn(withDrawVo.getRequestSn());
        withdrawLog.setWSn(withDrawVo.getWithDrawSn());
        String result = withdrawBankService.sendWithdrawRequest(withDrawVo);
        //更新提现表的状态
        if (null != result && result.equals("success")) {
            String withdrawBank = channelService.findChannelCodeByBankCode(withDrawVo.getWithdrawBankCode());
            if (!withdrawBank.equals(channel)) {//只要跨行不管大小额一律需要去查询转账结果
                withdraw.setStatus(WithdrawStatus.PROCESSING);// TODO: 2017/5/11 需要编写查询转账结果的接口之后获得转账结果之后再来更新提现表的状态
                withdrawLog.setLogType(WithdrawLogType.WAITTING_BANK_DEAL);
                withdrawLog.setMessage("提现已受理:提现金额" + withdrawDto.getAmount() + "元");
                log.info("提现已受理，更新提现记录成功");
            } else {
                withdraw.setStatus(WithdrawStatus.COMPLETE);
            }
            withdraw.setId(withdrawId);
            withdraw.setWPayBankCode(channel);
            withdrawService.updateWithdraw(withdraw);
            //更新账户余额变动的记录(本行提现是在这里进行更新账户余额变动记录)
            Withdraw withdraw2=withdrawService.selectByWSn(withDrawVo.getWithDrawSn());
            if (withdrawBank.equals(channel)) {
                int i = withdrawService.updateAfterWithdrawSuccess(withdraw2);
                if (i == 1) {
                    withdrawLog.setLogType(WithdrawLogType.SUCCESS);
                    withdrawLog.setMessage("提现成功:提现金额" + withdrawDto.getAmount() + "元");
                    log.info("提现成功，更新提现记录成功");
                } else {
                    withdrawLog.setLogType(WithdrawLogType.BUSINESS_ERROR);
                    withdrawLog.setMessage("提现成功，账户余额变更记录有误！");
                    log.error("提现成功，更新提现记录失败");
                }
            }
            withdrawLogService.addLog(withdrawLog);
            if(!withdrawBank.equals(channel)){
                return JSONResultGenerator.buildOperSuccessMessage("提现已受理，等待银行处理！");
            }
            return JSONResultGenerator.buildOperSuccessMessage("提现成功！");
        }
        withdraw.setId(withdrawId);
        withdraw.setStatus(WithdrawStatus.FAILURE);
        withdraw.setWPayBankCode(channel);
        withdrawService.updateWithdraw(withdraw);
        //失败了还原账户的余额
        BigDecimal balance = accountService.findBalanceById(withdrawDto.getAccountId());
        accountDTO.setAccountId(withdrawDto.getAccountId());
        accountDTO.setAvailableBalance(balance);
        accountDTO.setBalance(balance);
        accountDTO.setFreezeBalance(new BigDecimal(0.00));
        accountService.updateAccountBalanceBeforWithDraw(accountDTO);
        withdrawLog.setLogType(WithdrawLogType.BANK_ERROR);
        withdrawLog.setMessage("提现失败:" + result);
        withdrawLogService.addLog(withdrawLog);
        accountBillService.updateAccountBillFailure(BizzSys.SELF,withDrawVo.getWithDrawSn());
        return JSONResultGenerator.buildBusinessError("提现失败，请联系客服！");
    }
}
